package jeconbond.economic.natural.strategy;

import java.util.List;

import jeconbond.economic.market.strategy.IProcessDealStrategy;
import jeconbond.economic.production.IResourceNecessityInformer;
import jeconbond.economic.production.IResourceNecessityInformer.InfoItem;
import jeconbond.economic.resources.ResourceBasket;
import jeconbond.economic.resources.ResourceStorrage;
import jeconbond.economic.systems.natural.NaturalResourceRedestributionSystem;
import jeconbond.economic.systems.market.IMoneyAccount;
import jeconbond.economic.strategy.IMerchant;

public class NaturalMerchant implements IMerchant {
	private ResourceStorrage inputRS;
	private ResourceStorrage outputRS;
	private IResourceNecessityInformer informer;
	private int purchaseLevel;
	private NaturalResourceRedestributionSystem nrrs;
	private double EPS;

	public NaturalMerchant(
			ResourceStorrage inputRS, 
			ResourceStorrage outputRS,
			IResourceNecessityInformer informer,
			NaturalResourceRedestributionSystem nrrs,
			int purchaseLevel,
			double EPS
			) {
		this.inputRS = inputRS;
		this.outputRS = outputRS;
		this.informer = informer;
		this.nrrs = nrrs;
		this.purchaseLevel = purchaseLevel;
		this.EPS = EPS;
	}

	public NaturalMerchant(
			ResourceStorrage inputRS, 
			ResourceStorrage outputRS,
			IResourceNecessityInformer informer,
			NaturalResourceRedestributionSystem nrrs
	) {
		this(inputRS, outputRS, informer, nrrs, 0, 1e-5);
	}
	
	@Override
	public void processPurchase() {
		List<InfoItem> infoItemsList = informer.listInfoItems();
		if (enoughtResources(infoItemsList)) {
			for (InfoItem item : infoItemsList) {
				double val = receiveNecessaryValue(item);
				inputRS.storeResource(item.basket.type, val);
			}
		}
	}

	@Override
	public void setProcessDealStrategy(IProcessDealStrategy processDealStrategy) {
		throw new UnsupportedOperationException();
	}

	@Override
	public IMoneyAccount getMoneyAccount() {
		throw new UnsupportedOperationException();
	}

	private double receiveNecessaryValue(InfoItem item) {
		double valn = getNecessaryValue(item);
		double valr = nrrs.receiveResource(item.basket.type, valn);
		return valr;
	}

	private double getNecessaryValue(InfoItem item) {
		if (item.proirityLevel <= purchaseLevel) {
			double avail = inputRS.howMuchWasStored(item.basket.type);
			return Math.max(0.0, item.basket.value - avail);
		} else {
			return 0.0;
		}
	}

	private boolean enoughtResources(List<InfoItem> infoItemsList) {
		for (InfoItem item : infoItemsList) {
			double nec = getNecessaryValue(item);
			if (nec > EPS + nrrs.howMuchWasStored(item.basket.type)) {
				return false;
			}
		}
		return true;
	}

	public void processSelling() {
		for (ResourceBasket rb : outputRS.listBaskets()) {
			double val = outputRS.receiveResource(rb.type, rb.value);
			nrrs.storeResource(rb.type, val);
		}
	}
}
